package com.comleader.ldmapdownload.util.map;

import org.gdal.gdal.Band;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.Driver;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * @author 张志航
 * @description 用于根据坐标计算海拔的工具类
 * @date 2020-11-27 16:09
 */
@Component
@PropertySource(value = {"classpath:config/config.properties"}, encoding = "UTF-8")
public class GdalUtil {

    @Value("${tifPath}")
    private String tifPath;

    @Value("${gdalPath}")
    private String gdalPath;

    public static String TIF_PATH;

    public static Dataset hDataset;


    //当容器实例化当前受管Bean时@PostConstruct注解的方法会被自动触发，借此来实现静态变量初始化
    @PostConstruct
    public void init() {
        this.TIF_PATH = tifPath;
    }

    public static void initGdal() {
        //支持所有驱动
        gdal.AllRegister();
//要读取的文件，经纬度不可超过查询地图的范围，否则结果为null
//只读方式读取数据
        hDataset = gdal.Open(TIF_PATH, gdalconstConstants.GA_ReadOnly);
        //支持中文路径
        gdal.SetConfigOption("gdal_FILENAME_IS_UTF8", "YES");
        //图像的列和行
        Driver hDriver =  hDataset.GetDriver();
    }


    public static Integer getAltitude(double lon, double lat) {
        initGdal();
        //海拔
        Integer altitude = 0;

        //判断是否非空
        if (hDataset == null) {
            return 0;
        }

        //图像的列和行
        int iXSize = hDataset.getRasterXSize();
        int iYSize = hDataset.getRasterYSize();
        Band band = hDataset.GetRasterBand(1);
        //图像六要素
        double[] dGeoTrans = hDataset.GetGeoTransform();
//经纬度转行列号
        double dTemp = dGeoTrans[1] * dGeoTrans[5] - dGeoTrans[2] * dGeoTrans[4];
        int Xline = (int) ((dGeoTrans[5] * (lon - dGeoTrans[0]) - dGeoTrans[2] * (lat - dGeoTrans[3])) / dTemp + 0.5);
        int Yline = (int) ((dGeoTrans[1] * (lat - dGeoTrans[3]) - dGeoTrans[4] * (lon - dGeoTrans[0])) / dTemp + 0.5);
        //这里是DEM数据，所以声明一个int数组来存储，如果是其他数据类型，声明相应的类型即可
        int buf[] = new int[iXSize];

//循环遍历取出像元值
        for (int i = 0; i < iYSize; i++) {
            band.ReadRaster(0, i, iXSize, 1, buf);    //读取一行数据
            // 下面是输出像元值
            for (int j = 0; j < iXSize; j++) {
                //使用转化后的行列号 直接确定坐标点所在的像元值
                if (i == Yline && j == Xline) {
                    altitude = buf[j];
                    return altitude;
                }
            }
        }
        destoryGdal();
        return 0;
    }


    public static void destoryGdal(){
        hDataset.delete();
// 可选
        gdal.GDALDestroyDriverManager();
    }

}
